/**
 * Title: 系统
 * Description: sGateService
 * Company:心医国际数字医疗系统（大连） 有限公司
 * Copyright (c) 2016, 2017, Senyint. All rights reserved.
 * 
 * @author WangNaiFei
 * @version 1.0
 */

package com.senyint.sys.utils.spring;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;

import com.senyint.sys.utils.StringUtils;
import com.senyint.sys.utils.log.Log;

/**
 * {@code SpringUtils}工具类 获取spring上下文的工具 获取spring容器中的Bean
 * <p>
 * 
 * @author WangNaiFei, WangNaiFei@senyint.com
 * @date 2017年3月7日 下午2:44:09
 * @version 1.0 实现 ApplicationContextAware 获取spring上下文
 * @version 2.0 实现 BeanDefinitionRegistryPostProcessor 做动态手动bean处理
 * @since jdk1.7+
 */

/**
 * {@code SpringUtils}
 * 
 * @Description: TODO
 * <p>
 * @author WangNaiFei,WangNaiFei@senyint.com
 * @date 2018年3月7日 下午2:21:25
 * @version 1.0
 * @since jdk1.7+
 */
public class SpringUtils {

	/**
	 * 获取容器中的Bean
	 * <p>
	 * 
	 * @author WangNaiFei, WangNaiFei@senyint.com
	 * @date 2017年7月31日 上午11:38:29
	 * @version 1.0
	 * @param classId
	 * @param c
	 * @return
	 * @see
	 */
	public static <T> T getBean(String classId, Class<T> c, ApplicationContext applicationContext) throws NoSuchBeanDefinitionException {
		return applicationContext.getBean(classId, c);
	}

	/**
	 * 获取容器中的Bean
	 * <p>
	 * 
	 * @author WangNaiFei, WangNaiFei@senyint.com
	 * @date 2017年7月31日 上午11:38:14
	 * @version 1.0
	 * @param requiredType
	 * @return
	 * @see
	 */
	public static <T> T getBean(Class<T> requiredType, ApplicationContext applicationContext) throws NoSuchBeanDefinitionException {
		return applicationContext.getBean(requiredType);
	}
	// ==================== BeanDefinitionRegistryPostProcessor ======================================================================================================

	/**
	 * @Title: registerBean
	 * @Description: 注册bean
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2017年11月29日 下午2:14:17
	 * @version 1.0
	 * @param beanClass
	 * @param beanFactory
	 */
	public static void registerBean(Class<?> beanClass, BeanDefinitionRegistry registry) {
		registerBean(beanClass, null, registry);
	}

	/**
	 * @Title: registerBean
	 * @Description: 动态注册未实例化bean
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月6日 下午2:58:16
	 * @version 1.0
	 * @param beanClass
	 * @param scope
	 * @param autowireCandidate
	 * @param beanName
	 */
	public static void registerBean(Class<?> beanClass, String beanName, BeanDefinitionRegistry registry) {
		Assert.notNull(beanClass, "==> register bean class must not null");
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
		beanDefinitionBuilder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);
		AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
		if (!StringUtils.hasText(beanName)) {
			beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, registry);
		}
		registry.registerBeanDefinition(beanName, beanDefinition);
		// 注意 spring自动注入之后是不实例化的只是个类在spring中，spring在getBean时实例化，
		// ((DefaultListableBeanFactory)registry).getBean(beanName);
		Log.INSTANCE.debug("动态注册spring bean:{}, type:{}", beanName, beanClass);
	}

	/**
	 * @Title: registerSingletonBean
	 * @Description: 动态注册已实例化bean
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2017年11月28日 下午6:21:33
	 * @version 1.0
	 * @param beanName
	 * @param object
	 * @see #SingletonBeanRegistry.registerSingleton
	 */
	public static void registerSingletonBean(String beanName, Object object, ConfigurableListableBeanFactory beanFactory) {
		Assert.notNull(beanName, "==> register bean beanName must not null");
		Assert.notNull(object, "==> register bean object must not null");
		beanFactory.registerSingleton(beanName, object);
		Log.INSTANCE.debug("动态注册spring bean:{}, type:{}", beanName, object.getClass().getName());
	}

	/**
	 * @Title: registerSingletonBean
	 * @Description: 动态注册已实例化bean
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2019年2月22日 下午12:12:42
	 * @version 1.0
	 * @param beanName
	 * @param beanClass
	 * @param beanFactory
	 */
	public static void registerSingletonBean(String beanName, Class<?> beanClass, ConfigurableListableBeanFactory beanFactory) {
		Assert.notNull(beanClass, "==> register bean class must not null");
		registerSingletonBean(beanName, beanFactory.createBean(beanClass), beanFactory);
	}

	/**
	 * @Title: autowireBean
	 * @Description: TODO
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2019年2月28日 上午10:33:02
	 * @version 1.0
	 * @param bean
	 * @param applicationContext
	 */
	public static void autowireBean(Object bean, ApplicationContext applicationContext) {
		applicationContext.getAutowireCapableBeanFactory().autowireBean(bean);
	}

}
